package cn.grayrelese.rule;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.netflix.loadbalancer.Server;
import com.netflix.loadbalancer.ZoneAvoidanceRule;
import com.netflix.niws.loadbalancer.DiscoveryEnabledServer;
import org.apache.commons.lang.StringUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.*;

/**
 * @description 灰度自定义路由规则
 * @author chenluqiang
 * @date 2020-04-02
 */
public class GrayMetadataRule extends ZoneAvoidanceRule {
//    Logger logger = LoggerFactory.getLogger(GrayMetadataRule.class);

    @Override
    public Server choose(Object key) {
        ServletRequestAttributes servletRequestAttributes  = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes();
        //1.从请求头获取version信息
        String version =servletRequestAttributes.getRequest().getHeader("version");
        //2.获取服务实例列表
        List<Server> serverList = this.getLoadBalancer().getAllServers();
        //3.循环serverList，选择version匹配的服务并返回
        List<Server> notVersionSeverList = new ArrayList<>();
        List<Server> versionSeverList = new ArrayList<>();
        for (Server server : serverList) {
            Map<String, String> metadata = ((DiscoveryEnabledServer) server).getInstanceInfo().getMetadata();
            String metaVersion = metadata.get("version");
            if (StringUtils.isNotBlank(metaVersion)) {
                if (metaVersion.equals(version)) {
                    versionSeverList.add(server);
                    continue;
                }
            }
            if(!metadata.containsKey("version")){
                notVersionSeverList.add(server);
            }
        }
        //4.如果没有匹配到主机,则随机分配没有version的主机
        Server s = null;
        try{
            if(!versionSeverList.isEmpty()&&versionSeverList.size()!=0) {
                //随机获取灰度主机
                s = versionSeverList.get(new Random().nextInt(versionSeverList.size()));
            }else {
                //随机获取非灰度主机
                s = notVersionSeverList.get(new Random().nextInt(notVersionSeverList.size()));
            }
        }catch (IllegalArgumentException e){
            //过滤该请求，不往下级服务去转发请求，到此结束
            HttpServletResponse response = servletRequestAttributes.getResponse();
            Map<String,String> messages = new HashMap<>();
            messages.put("result",String.format("用户%s：没有可用的服务器!",version));
            messages.put("status","success");
            this.responseMessages(response,messages);
        }
        return s;
    }
    /**
     * 响应消息给页面
     * @param response
     * @param messages
     */
    private void responseMessages(HttpServletResponse response,Map<String,String> messages) {
        response.setStatus(200);
        response.setCharacterEncoding("utf-8");
        response.setContentType("text/html;charset=UTF-8");
        try {
            ServletOutputStream outputStream = response.getOutputStream();
            String json = new ObjectMapper().writeValueAsString(messages);
            outputStream.write(json.getBytes());
            outputStream.flush();
            outputStream.close();
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }
}
